 .386                   ;enable instructions
        .xmm                    ;enable instructions
        .model flat,c           ;use C naming convention (stdcall is default)

	include algo-types.inc
	include macros.inc
	extrn   printf:near

		.code

;void initStack(struct sqStack s, int *ary, int len)
initStack proc uses eax esi,
	q: ptr sqStack, ary: ptr dword, len: dword

	mov esi, q
	mov eax, ary
	mov (sqStack ptr [esi]).base, eax
	mov (sqStack ptr [esi]).top, eax
	mov eax, len
	mov (sqStack ptr [esi]).len, eax
	ret
initStack endp

;int stackFull(struct sqStack *s)
;return: eax = 1 if full; 0 if not full
stackFull proc uses esi ebx,
	s: ptr sqStack

	mov esi, s
	mov eax, 1
	;if((s->top - s->base) >= s->len) {
	mov ebx, [(sqStack ptr [esi]).top]
	sub ebx, [(sqStack ptr [esi]).base]
	shr ebx, 2 ;ebx = ebx / 4
	cmp ebx, [(sqStack ptr [esi]).len]
	jnb exitp
	mov eax, 0

exitp:
	ret
stackFull endp

;int stackEmpty(struct sqStack *s)
;return: eax = 1 if empty; 0 if not empty
stackEmpty proc uses ebx esi,
	s: ptr sqStack

	mov esi, s
	mov eax, 1
	;if (s->top == s->base)
	mov ebx, [(sqStack ptr [esi]).top]
	cmp ebx, [(sqStack ptr [esi]).base]
	je exitp
	mov eax, 0

exitp:
	ret
stackEmpty endp

;int pushdata(struct sqStack *s, int data)
;return: eax = 1 if fail; 0 if OK
pushdata proc uses esi ecx,
	s: ptr sqStack, data: dword

	mov esi, s
	invoke stackFull, esi
	cmp eax, 1
	je exitp ;stack is full
	
	;here eax is 0
	mov ecx, (sqStack ptr [esi]).top
	push data
	pop [ecx]
	add (sqStack ptr [esi]).top, 4

exitp:
	ret
pushdata endp

;int popdata(struct sqStack *s, int* data)
;return: eax = 1 if fail; 0 if OK
popdata proc uses ecx esi,
	s: ptr sqStack, data: ptr dword

	mov esi, s
	invoke stackEmpty, esi
	cmp eax, 1
	je exitp ;stack is empty
	
	;here eax is 0
	sub (sqStack ptr [esi]).top, 4 ;top - 4
	mov ecx, (sqStack ptr [esi]).top
	push [ecx]
	mov ecx, data
	pop [ecx]

exitp:
	ret
popdata endp

;================test code================

STACKLEN = 20
 .data                   ;initialized data
pfstr   db      "finished stack test",0dh,0ah,0
startPushStr db "Start to push" ,0dh,0ah,0
startPopStr db "Start to pop" ,0dh,0ah,0
statckdata dword 0

psstack sqStack <>

 .data?                  ;uinitialized data
array_stack dword STACKLEN dup(?)

.code
testStack    proc
		mov esi, offset psstack
		invoke initStack, esi, addr array_stack, STACKLEN

		;test
		invoke stackEmpty, esi ;eax = 1
		invoke stackFull, esi;eax = 0

		mPutStr startPushStr

		mov ecx, STACKLEN + 1
		mov ebx, 0
	loop_push:
		inc ebx
		invoke pushdata, esi, ebx
		cmp eax, 1
		je next ;finished
		
		mPutNum ebx ;print it
		loop loop_push

	next:
		mPutCRLF

		;start pop
		mPutStr startPopStr
	loop_pop:
		invoke popdata, esi, addr statckdata
		cmp eax, 1
		je finish
		mPutNum statckdata
		jmp loop_pop

	finish:
		mPutCRLF
        mPutStr pfstr ;finished all
        xor     eax,eax
        ret
testStack    endp

end
